#include "proxy/dns/dns_solution.h"

namespace proxy{

  DnsServer::DnsServer(boost::asio::io_service &io_serivce)
    :io_serivce_(io_serivce),
    is_running_(false){

  }

  bool DnsServer::StartDnsServer(){
    if (dns_socket_){
      return false;
    }

    try{
      dns_socket_.reset(new boost::asio::ip::udp::socket(io_serivce_,
        boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 10009)));
      //dns_socket_->bind(boost::asio::ip::udp::endpoint(
      //  boost::asio::ip::udp::v4(), DEFAULT_DNS_PORT));
    }
    catch (std::exception &e){
      // BIND ERROR
      LOG(ERROR) << e.what();
      dns_socket_.reset();
      return false;
    }
    return StartReceiveDnsRequestion();
  }

  void DnsServer::StopDnsServer(){
    
  }

  bool DnsServer::StartReceiveDnsRequestion(){
    if (!dns_socket_){
      return false;
    }
    UdpEndpointPtr client_endpoint(new boost::asio::ip::udp::endpoint);
    dns_socket_->async_receive_from(
      boost::asio::buffer(recv_buffer_, DNS_RECEIVE_BUFFER_SIZE),*client_endpoint,
      boost::bind(&DnsServer::HandleReceiveDnsRequestion, shared_from_this(),
      client_endpoint,
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));
    return true;
  }

  void DnsServer::HandleReceiveDnsRequestion(UdpEndpointPtr client_endpoint,
    const boost::system::error_code& error, std::size_t bytes_transferred){
    if (error){
      LOG(ERROR) << error.message();
      return;
    }
    // Debug output
    LOG(INFO).write(recv_buffer_, bytes_transferred);
    LOG(INFO) << client_endpoint->address().to_string();
    StartReceiveDnsRequestion();
  }

}